#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "stack.h"
/*
函数名称：
    init_stack
说明:
    初始化栈
参数:
    stack[in/out]:栈指针
	data_size[in]:栈每个块的内存大小（最好使用sizeof计算）
返回值：
    -1参数错误
    0成功
*/
int init_stack(stack_t * stack,int data_size)
{
    int i = 0;
    if(!stack || data_size <=0)
        return -1;
    //分配存储空间
    for(i = 0;i< STACK_MAX_COUNT;i++)
    {
        stack->data_ptr[i] = (void *)malloc(data_size);
        memset(stack->data_ptr[i],0,sizeof(data_size));
    }
    //初始化控制变量
    stack->top = 0;
	stack->count = 0;
    stack->data_size = data_size;
    //初始化互斥锁
#if !defined(WIN32)
    pthread_mutex_init(&stack->mtx, NULL);
#else
	InitializeCriticalSection(&stack->mtx);
#endif
    return 0;
}
/*
函数名称
    free_stack
说明
    释放栈列资源
参数
    stack[in]:环形队列指针
返回值
    -1参数错误
    0成功
*/
int free_stack(stack_t * stack)
{
     int i = 0;
     if(!stack)   
        return -1;
    //加锁
#if !defined(WIN32)
    pthread_mutex_lock(&stack->mtx); 
#else
	EnterCriticalSection(&stack->mtx);
#endif
    //释放内存
    for(i = 0;i<STACK_MAX_COUNT;i++)
    {
        if(stack->data_ptr[i])
        {
            free(stack->data_ptr[i]);
            stack->data_ptr[i] = 0;
        }
    }
    //归零控制变量
    stack->top = 0;
	stack->count = 0;
    stack->data_size = 0;
#if !defined(WIN32)
    //解锁
    pthread_mutex_unlock(&stack->mtx);
    //销毁互斥锁
    pthread_mutex_destroy(&stack->mtx);
#else
	LeaveCriticalSection(&stack->mtx);
	DeleteCriticalSection(&stack->mtx);
#endif
}
/*
函数名称：
    empty_stack
说明
    清空栈的内容
参数
    stack[in]:队列指针
返回值
    -1参数错误
    0 成功
*/
int empty_stack(stack_t * stack)
{
    int i= 0;
    if(!stack)
        return -1;
    //加锁
#if !defined(WIN32)
    pthread_mutex_lock(&stack->mtx);
#else
	EnterCriticalSection(&stack->mtx);
#endif
    //清空内容
    for(i = 0;i<STACK_MAX_COUNT;i++)
    {
        if(stack->data_ptr[i])
        {
            memset(stack->data_ptr[i],0,stack->data_size);
        }
    }
    //复位标识量
    stack->top = 0;
	stack->count = 0;
    //解锁
#if !defined(WIN32)
    pthread_mutex_unlock(&stack->mtx);
#else
	LeaveCriticalSection(&stack->mtx);
#endif
}
/*
函数名称：
    pop_stack
说明
     数据出队，将数据复制到data指向的存储空间
参数
    stack[in]:栈指针
    data[out]:数据存储取指针
返回值
    -1参数错误
    -2队列为空
    -3失败，栈内存错误
    0 成功
*/
int pop_stack(stack_t * stack,void *data)
{
    if(!stack || !data)
        return -1;
    //加锁
#if !defined(WIN32)
    pthread_mutex_lock(&stack->mtx);
#else
	EnterCriticalSection(&stack->mtx);
#endif
     //判断栈是否为空   
    if(stack->count <= 0)
    {
       //空栈
#if !defined(WIN32)
		pthread_mutex_unlock(&stack->mtx);
#else
		LeaveCriticalSection(&stack->mtx);
#endif
        return -2;
    }
        
     //出栈   
    if(stack->data_ptr[stack->top])
    {
		stack->top--;
        memcpy(data,stack->data_ptr[stack->top], stack->data_size);
        memset(stack->data_ptr[stack->top],0, stack->data_size);
		stack->count--;
    }else
    {
        //栈内存错误
 #if !defined(WIN32)
		pthread_mutex_unlock(&stack->mtx);
#else
		LeaveCriticalSection(&stack->mtx);
#endif
        return -3;
    }
    //解锁
#if !defined(WIN32)
    pthread_mutex_unlock(&stack->mtx);
#else
	LeaveCriticalSection(&stack->mtx);
#endif
    return 0;  
}
/*
函数名称：
    push_stack
说明
     数据入栈，将data指针空间的数据拷贝到栈中
参数
    stack[in]:栈指针
    data[in]:数据指针
返回值
    -1参数错误
    -2栈已满
    -3队列内存错误
    0成功
*/
int push_stack(stack_t * stack,void *data)
{
    if(!stack || !data)
        return -1;
    //加锁
#if !defined(WIN32)
    pthread_mutex_lock(&stack->mtx);
#else
	EnterCriticalSection(&stack->mtx);
#endif
    //判断是否满栈
    if(stack->count >= STACK_MAX_COUNT)
    {   
        //满栈
 #if !defined(WIN32)
		pthread_mutex_unlock(&stack->mtx);
#else
		LeaveCriticalSection(&stack->mtx);
#endif
         return -2;
    }
      //入栈
     if(stack->data_ptr[stack->top])
     {
         memcpy(stack->data_ptr[stack->top],data, stack->data_size);
         stack->top++;
		 stack->count++;
     }else
     { 
         //栈内存错误
 #if !defined(WIN32)
		pthread_mutex_unlock(&stack->mtx);
#else
		LeaveCriticalSection(&stack->mtx);
#endif
         return -3;
     }
     //解锁
 #if !defined(WIN32)
	pthread_mutex_unlock(&stack->mtx);
#else
	LeaveCriticalSection(&stack->mtx);
#endif
     return 0;
    
}
